﻿namespace SharePoint.ImportExport.Importer
{
    using System;
    using System.IO;
    using System.Reflection;
    using Microsoft.SharePoint;
    
    /// <summary>
    /// This is a helper class for dealing with MIME encoded data
    /// </summary>
    public class FixMHTML
    {
        /// <summary>
        /// Reads a Mime encoded file and extracts the images and adds them to a picturelibrary
        /// </summary>
        /// <param name="fileName">MIME encoded file</param>
        /// <param name="folderName">Temporay directory</param>
        /// <param name="web">SPWeb object</param>
        /// <returns>HTML string</returns>
        public static string ReadFromFile(string fileName, string folderName, Microsoft.SharePoint.SPWeb web)
        {
            Guid listID = Guid.Empty;
            foreach (Microsoft.SharePoint.SPList list in web.Lists)
            {
                if (list.BaseTemplate == SPListTemplateType.PictureLibrary)
                {
                    listID = list.ID;
                    break;
                }

                if (list.Title == "Images")
                {
                    listID = list.ID;
                    break;
                }
            }

            Microsoft.SharePoint.SPDocumentLibrary picLib = null;
            string libUrl = string.Empty;
            if (listID != Guid.Empty)
            {
                picLib = (Microsoft.SharePoint.SPDocumentLibrary)web.Lists[listID];
                libUrl = web.ServerRelativeUrl + "/" + picLib.RootFolder.Url;
            }

            CDO.MessageClass msg = new CDO.MessageClass();
            ADODB.Stream stream = new ADODB.StreamClass();
            //// Open empty stream
            stream.Open(Missing.Value, ADODB.ConnectModeEnum.adModeUnknown, ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified, string.Empty, string.Empty);
            stream.LoadFromFile(folderName + "\\" + fileName);
            stream.Flush();
            string mimeData = File.ReadAllText(folderName + "\\" + fileName);
            if (!mimeData.StartsWith("MIME-"))
            {
                return mimeData.Trim();
            }

            msg.MimeFormatted = true;
            msg.DataSource.OpenObject(stream, "_Stream");
            msg.DataSource.Save();

            int i = msg.BodyParts.Count;
            string html = msg.HTMLBody.Trim();
            for (int ii = 1; ii <= i; ii++)
            {
                string ext = msg.BodyParts[ii].ContentMediaType;
                ext = ext.Substring(ext.IndexOf("/") + 1);
                string encoding = string.Empty;

                int j = msg.BodyParts[ii].Fields.Count;
                string name = string.Empty;
                if (ext == "related")
                {
                    int partCount = msg.BodyParts[ii].BodyParts.Count;

                    for (int iii = 1; iii <= partCount; iii++)
                    {
                        ext = msg.BodyParts[ii].BodyParts[iii].ContentMediaType;
                        ext = ext.Substring(ext.IndexOf("/") + 1);
                        j = msg.BodyParts[ii].BodyParts[iii].Fields.Count;
                        for (int jj = 0; jj < j; jj++)
                        {
                            switch (msg.BodyParts[ii].BodyParts[iii].Fields[jj].Name)
                            {
                                case "urn:schemas:mailheader:content-id":
                                    {
                                        name = msg.BodyParts[ii].BodyParts[iii].Fields[jj].Value.ToString();
                                        name = name.Substring(1, name.Length - 2);
                                        break;
                                    }

                                case "urn:schemas:mailheader:content-transfer-encoding":
                                    {
                                        encoding = msg.BodyParts[ii].BodyParts[iii].Fields[jj].Value.ToString();
                                        break;
                                    }
                            }
                        }

                        switch (encoding)
                        {
                            case "quoted-printable":
                            case "base64":
                            case "uuencode":
                                {
                                    if (name != string.Empty)
                                    {
                                        msg.BodyParts[ii].BodyParts[iii].SaveToFile(folderName + "\\" + name + "." + ext);
                                    }
                                    
                                    break;
                                }
                        }

                        if (picLib != null && name != string.Empty)
                        {
                            byte[] data = File.ReadAllBytes(folderName + "\\" + name + "." + ext);
                            File.Delete(folderName + "\\" + name + "." + ext);

                            try
                            {
                                picLib.RootFolder.Files.Add(name + "." + ext, data);
                                picLib.RootFolder.Update();
                            }
                            catch
                            {
                            }
                        }

                        if (name != string.Empty)
                        {
                            html = html.Replace("img src=cid:" + name, "img src=\"" + libUrl + "/" + name + "." + ext + "\"");
                        }
                    }
                }
                else
                {
                    name = string.Empty;

                    for (int jj = 0; jj < j; jj++)
                    {
                        switch (msg.BodyParts[ii].Fields[jj].Name)
                        {
                            case "urn:schemas:mailheader:content-id":
                                {
                                    name = msg.BodyParts[ii].Fields[jj].Value.ToString();
                                    name = name.Substring(1, name.Length - 2);
                                    break;
                                }

                            case "urn:schemas:httpmail:attachmentfilename":
                                {
                                    name = msg.BodyParts[ii].Fields[jj].Value.ToString();
                                    ext = name.Substring(name.IndexOf(".") + 1);
                                    name = name.Substring(0, name.Length - ext.Length - 1);
                                    break;
                                }

                            case "urn:schemas:mailheader:content-transfer-encoding":
                                {
                                    encoding = msg.BodyParts[ii].Fields[jj].Value.ToString();
                                    break;
                                }
                        }
                    }
                    
                    switch (encoding)
                    {
                        case "quoted-printable":
                        case "base64":
                        case "uuencode":
                            {
                                msg.BodyParts[ii].SaveToFile(folderName + "\\" + name + "." + ext);
                                break;
                            }
                    }

                    if (picLib != null && name != string.Empty)
                    {
                        byte[] data = File.ReadAllBytes(folderName + "\\" + name + "." + ext);
                        File.Delete(folderName + "\\" + name + "." + ext);

                        try
                        {
                            picLib.RootFolder.Files.Add(name + "." + ext, data);
                            picLib.RootFolder.Update();
                            libUrl = web.ServerRelativeUrl + "/" + picLib.RootFolder.Url;
                        }
                        catch
                        {
                        }
                    }

                    if (name != string.Empty)
                    {
                        html = html.Replace("img src=cid:" + name, "img src=\"" + libUrl + "/" + name + "." + ext + "\"");
                    }
                }
            }

            stream.Close();
            System.Runtime.InteropServices.Marshal.ReleaseComObject(stream);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(msg);
            return html;
        }

        /// <summary>
        /// Reads a Mime string and extracts the images and adds them to a picturelibrary
        /// </summary>
        /// <param name="mimeEncodedString">MIME encoded string</param>
        /// <param name="folderName">Temporay directory</param>
        /// <param name="web">SPWeb object</param>
        /// <returns>HTML string</returns>
        public static string ExtractDataAndCleanUpFile(string mimeEncodedString, string folderName, Microsoft.SharePoint.SPWeb web)
        {
            Guid listID = Guid.Empty;
            foreach (Microsoft.SharePoint.SPList list in web.Lists)
            {
                if (list.BaseTemplate == SPListTemplateType.PictureLibrary)
                {
                    listID = list.ID;
                    break;
                }
                
                if (list.Title == "Images")
                {
                    listID = list.ID;
                    break;
                }
            }

            Microsoft.SharePoint.SPDocumentLibrary picLib = null;
            if (listID != Guid.Empty)
            {
                picLib = (Microsoft.SharePoint.SPDocumentLibrary)web.Lists[listID];
            }
            
            string boundary = mimeEncodedString.Substring(mimeEncodedString.IndexOf("boundary=\"") + 10);
            boundary = "--" + boundary.Substring(0, boundary.IndexOf("\""));
            ////Fix Domino MIME bug
            while (mimeEncodedString.IndexOf(" " + boundary) > 0)
            {
                mimeEncodedString = mimeEncodedString.Replace(" " + boundary, boundary);
            }
            
            while (mimeEncodedString.IndexOf(" Content-Type:") > 0)
            {
                mimeEncodedString = mimeEncodedString.Replace(" Content-Type:", "Content-Type:");
            }
            
            while (mimeEncodedString.IndexOf(" Content-ID:") > 0)
            {
                mimeEncodedString = mimeEncodedString.Replace(" Content-ID:", "Content-ID:");
            }

            CDO.MessageClass msg = new CDO.MessageClass();
            ADODB.Stream stream = new ADODB.StreamClass();
            //// Open empty stream
            stream.Open(Missing.Value, ADODB.ConnectModeEnum.adModeUnknown, ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified, string.Empty, string.Empty);
            string fileName = folderName + "\\file.eml";
            File.WriteAllText(fileName, "MIME-Version: 1.0\r\n" + mimeEncodedString);
            stream.LoadFromFile(fileName);
            stream.Flush();
            msg.DataSource.OpenObject(stream, "_Stream");
            msg.DataSource.Save();
            int i = msg.BodyParts.Count;
            string html = msg.HTMLBody.Trim();
            for (int ii = 1; ii <= i; ii++)
            {
                string ext = msg.BodyParts[ii].ContentMediaType;
                ext = ext.Substring(ext.IndexOf("/") + 1);
                int j = msg.BodyParts[ii].Fields.Count;
                string name = string.Empty;
                for (int jj = 0; jj < j; jj++)
                {
                    if (msg.BodyParts[ii].Fields[jj].Name == "urn:schemas:mailheader:content-id")
                    {
                        name = msg.BodyParts[ii].Fields[jj].Value.ToString();
                        name = name.Substring(1, name.Length - 2);
                        break;
                    }
                }

                ADODB.Stream stream2 = msg.BodyParts[ii].GetDecodedContentStream();
                stream2.SaveToFile(folderName + "\\" + name + "." + ext, ADODB.SaveOptionsEnum.adSaveCreateOverWrite);
                string libUrl = string.Empty;
                if (picLib != null)
                {
                    byte[] data = File.ReadAllBytes(folderName + "\\" + name + "." + ext);
                    File.Delete(folderName + "\\" + name + "." + ext);

                    try
                    {
                        picLib.RootFolder.Files.Add(name + "." + ext, data);
                        picLib.RootFolder.Update();
                        libUrl = web.ServerRelativeUrl + "/" + picLib.RootFolder.Url;
                    }
                    catch
                    {
                    }
                }

                html = html.Replace("img src=cid:" + name, "img src=\"" + libUrl + "/" + name + "." + ext + "\"");
            }

            File.Delete(fileName);
            return html;
        }
    }
}
